package com.anche.cywebnew.Utils.netsdk;

import com.sun.jna.Native;
import com.sun.jna.Platform;

import java.io.*;
import java.net.URL;

/**
 * 将动态链接库加载到系统临时文件夹内
 */
public class LoadHelper {
    public synchronized static Object loadDll(String libName, Class<?> className) {
        String libExtension = ".dll", systemType = "win";
        switch (Platform.getOSType()) {
            case Platform.LINUX:
                libExtension = ".so";
                systemType = "linux";
        }
        String libFullName = libName + libExtension;

        String nativeTempDir = System.getProperty("user.home");

        if (libName.contains("HCNetSDK")) {
            systemType += System.getProperty("sun.arch.data.model");
            File extractedLibFile = new File(nativeTempDir + systemType + File.separator + libFullName);
            if (!extractedLibFile.exists()) {
                URL url = className.getResource(systemType);
                File srcFile = new File(url.getPath());
                File destFile = new File(nativeTempDir);
                try {
                    System.out.println("源目录：" + srcFile.getAbsolutePath() + "，目标目录：" + destFile.getAbsolutePath());
                    copyFolder(srcFile, destFile);
                    System.out.println("拷贝成功");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return Native.loadLibrary(nativeTempDir + File.separator + systemType + File.separator + libFullName, className);
        } else {
            //获取操作系统缓存的临时目录
            InputStream in = null;
            BufferedInputStream reader = null;
            FileOutputStream writer = null;
            File extractedLibFile = new File(nativeTempDir + File.separator + libFullName);
            //临时文件
            if (!extractedLibFile.exists()) {
                try {
                    systemType += System.getProperty("sun.arch.data.model");
                    in = className.getResourceAsStream(systemType + "/" +
                            libFullName);
                    if (in == null)
                        in = className.getResourceAsStream(libFullName);
                    reader = new BufferedInputStream(in);
                    writer = new FileOutputStream(extractedLibFile);
                    byte[] buffer = new byte[1024];
                    while (reader.read(buffer) > 0) {
                        writer.write(buffer); //将 dll/so/dylib 写入临时文件中
                        buffer = new byte[1024];
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    if (in != null)
                        try {
                            in.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    if (writer != null)
                        try {
                            writer.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                }
            }
            String temp = extractedLibFile.toString();
            String dllName = temp.substring(0, temp.lastIndexOf("."));
            return Native.loadLibrary(dllName, className);
        }

    }

    private static void copyFolder(File srcFile, File destFile) throws IOException {

        if (srcFile.isDirectory()) {
            File newFolder = new File(destFile, srcFile.getName());
            newFolder.mkdirs();
            File[] fileArray = srcFile.listFiles();

            for (File file : fileArray) {
                copyFolder(file, newFolder);
            }

        } else {
            File newFile = new File(destFile, srcFile.getName());
            copyFile(srcFile, newFile);
        }

    }

    private static void copyFile(File srcFile, File newFile) throws IOException {
        // TODO Auto-generated method stub
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(newFile));

        byte[] bys = new byte[1024];
        int len = 0;
        while ((len = bis.read(bys)) != -1) {
            bos.write(bys, 0, len);
        }
        bos.close();
        bis.close();

    }
}
